/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package at.ofai.gate.riplugin2;

import gate.Resource;
import gate.creole.ResourceInstantiationException;
import gate.creole.metadata.CreoleParameter;
import gate.creole.metadata.CreoleResource;
import gate.creole.metadata.Optional;
import gate.event.CreoleEvent;
import gate.event.CreoleListener;
import gate.gui.ActionsPublisher;
import gate.util.GateRuntimeException;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractAction;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.misc.HighFreqTerms;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;

/**
 * A LR representing a lucene index.
 * This LR does not have to initially contain any index data, it can be
 * created "empty" and the IRBuildIndexLucenePR is used to fill it with actual
 * index data.
 * 
 * @author Johann Petrak
 */
@CreoleResource(
    name = "RILuceneIndexLR2",
    //interfaceName = "",
    comment = "Lucene index for use with the RI Plugin",
    icon = "ontology"
    //helpURL = "http://gate.ac.uk/userguide/sec:ontologies:ontoplugin:owlim"
    )
public class RIIndexLuceneLR
  extends RIIndexLR
  implements ActionsPublisher, CreoleListener{
  @Optional
  @CreoleParameter(comment="Directory that should contain the lucene index directory")
  /**
   * Set the URL of the directory that contains the random index data or
   * should contain the random index data (if it is still to be created).
   */
  public void setDirectoryURL(URL directoryURL) {
    this.directoryURL = directoryURL;
  }
  public URL getDirectoryURL() {
    return directoryURL;
  }
  protected URL directoryURL;

  // Fields and their getters
  File luceneIndexDir = null;
  public File getLuceneIndexDir() { return luceneIndexDir; }

  private IndexReader indexReader = null;


  @Override
  public Resource init() throws ResourceInstantiationException {
    if(getDirectoryURL() == null || getDirectoryURL().equals("")) {
      throw new ResourceInstantiationException("directoryURL must be set!");
    }
    // check the directory and see if we have index files in there.
    // set the internal flags accordingly.
    File directory = gate.util.Files.fileFromURL(directoryURL);
    if(!directory.exists()) {
      throw new ResourceInstantiationException("No directory exists with URL: "+directoryURL);
    }
    luceneIndexDir = new File(directory,"index");
    return this;
  }


  /**
   * This opens the lucene index read-only and returns sets the index reader
   * object. 
   */
  public boolean open() {
    if(!hasData()) {
      return false;
    }
    try {
      indexReader = IndexReader.open(FSDirectory.open(getLuceneIndexDir()), true);
      return true;
    } catch (Exception ex) {
      throw new GateRuntimeException("Could not open lucene index "+getLuceneIndexDir(),ex);
    }
  }

  public void close() {
    if(indexReader != null) {
      try {
        indexReader.close();
      } catch (IOException ex) {
        throw new GateRuntimeException("Could not close lucene index "+getLuceneIndexDir(),ex);
      }
      indexReader = null;
    }
  }

  public boolean isOpen() {
    // TODO
    return true;
  }

  public boolean hasData() {
    // TODO:
    return true;
  }
  
  /**
   * Return the document frequency, i.e. the number of documents the term 
   * occurs in.
   * 
   * @param termString
   * @return the document frequency
   */
  public int docFreq(String termString) {
    try {
      return indexReader.docFreq(new Term("contents",termString));
    } catch (IOException ex) {
      throw new GateRuntimeException("Problem accessing lucene index "+getLuceneIndexDir(),ex);
    }
  }
  
  /**
   * Return the number of documents in the index.
   * 
   * @return 
   */
  public int numDocs() {
    return indexReader.numDocs();
  }
  
  /**
   * Return the total term frequency, i.e. the total number of times the
   * term occurs in all documents. 
   * 
   * @param termString
   * @return a long with the total term frequency
   */
  public long getTotalTermFreq(String termString) {    
    long totalTF;
    try {
      totalTF = HighFreqTerms.getTotalTermFreq(indexReader, new Term("contents",termString));
    } catch (Exception ex) {
      throw new GateRuntimeException("Problem accessing lucene index "+getLuceneIndexDir(),ex);
    }
    return totalTF; 
  }

  /**
   * Return the number of unique terms in the index (over all fields, so 
   * in our case, this includes the unique document names!).
   * If the document names are all different then the actual number of 
   * unique terms in the "contents" field is the number returned here minus
   * what method numDocs() returns.
   * @return 
   */
  public long getUniqueTermCount() {
    try {
      return indexReader.getUniqueTermCount();
    } catch (IOException ex) {
      throw new GateRuntimeException("Problem accessing lucene index "+getLuceneIndexDir(),ex);
    }
  }
  
  public List<IndexType> getIndextypes() {
    List<IndexType> ret = new ArrayList<IndexType>();
    return ret;
  }
  
  public enum IndexType {
    Lucene, SVTermvectors, SVDocumentvectors
  }


  // for special purpose stuff, also allow access to the underlying libraries?
  // getLuceneIndexReader
  // getSV...

  // implement ActionsPublisher methods
  protected List<AbstractAction> actionsList;
  public List getActions() {
    return actionsList;
  }

  // ************ Creole Listener Methods ************
  public void resourceLoaded(CreoleEvent ce) {
    // do nothing
  }

  public void datastoreClosed(CreoleEvent ce) {
  }

  public void resourceRenamed(Resource resource, String oldname, String newname) {
  }

  public void datastoreOpened(CreoleEvent ce) {
  }

  public void datastoreCreated(CreoleEvent ce) {
  }

  public void resourceUnloaded(CreoleEvent ce) {
  }



}
